package bdhub.littletail.app.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import bdhub.littletail.app.LittleTailApplication;
import bdhub.littletail.lib.utils.StringUtil;

public class Storage {
	
	private static Storage INSTANCE;
	
	private static final String COMMON_FOLDER = "common";
	private static final String FILE_SAVE = "/tmp";
	
	private JSONObject mToken;
	
    private static ConcurrentHashMap<String, ReentrantReadWriteLock> fileLocks = new ConcurrentHashMap();

    private static ReentrantReadWriteLock getLock(String path)
    {
        ReentrantReadWriteLock lock = (ReentrantReadWriteLock)fileLocks.get(path);
        if (lock == null) {
            lock = new ReentrantReadWriteLock();
            ReentrantReadWriteLock oldLock = (ReentrantReadWriteLock)fileLocks.putIfAbsent(path, lock);
            if (oldLock != null) {
                lock = oldLock;
            }
        }
        return lock;
    }
	
	public static Storage getInstance() {
		if (null == INSTANCE) {
			INSTANCE = new Storage();
		}
		return INSTANCE;
	}
	
	public void setToken(JSONObject data) {
		mToken = data;
		File file = new File(LittleTailApplication.sharedInstance().getDir(COMMON_FOLDER, 0) + FILE_SAVE);
		if (null != data) {
			saveContentToFile(data.toJSONString(), file);
		} else {
			file.delete();
		}
	}
	
	public JSONObject getToken(){
		if (null == mToken) {
			File file = new File(LittleTailApplication.sharedInstance().getDir(COMMON_FOLDER, 0) + FILE_SAVE);
			if (file.exists()) {
				String jsonString = readContentFromFile(file);
				if (!StringUtil.isEmpty(jsonString)) {
					mToken = JSON.parseObject(jsonString);
				}
			}
		}
		return mToken;
	}
	
    private static String readContentFromFile(File fileForRead) {
        Lock readLock = getLock(fileForRead.getAbsolutePath()).readLock();
        readLock.lock();
        FileInputStream in = null;
        InputStreamReader reader = null;
        BufferedReader breader = null;
        try {
            in = new FileInputStream(fileForRead);
            reader = new InputStreamReader(in, "utf-8");
            breader = new BufferedReader(reader);

            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = breader.readLine()) != null) {
                sb.append(line);
            }
            return AESEncryptor.decrypt(SystemTool.getPhoneIMEI(), sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeQuietly(breader);
            closeQuietly(reader);
            closeQuietly(in);
            readLock.unlock();
        }
        return null;
    }
    
    private static boolean saveContentToFile(String content, File fileForSave) {
        Lock writeLock = getLock(fileForSave.getAbsolutePath()).writeLock();
        boolean succeed = true;
        FileOutputStream out = null;
        if (writeLock.tryLock()) {
            try
            {
                out = new FileOutputStream(fileForSave, false);
                out.write(AESEncryptor.encrypt(SystemTool.getPhoneIMEI(), content).getBytes("utf-8"));
            }
            catch (Exception e) {
                e.printStackTrace();
                succeed = false;
            } finally {
                if (out != null) {
                    closeQuietly(out);
                }
                writeLock.unlock();
            }
        }
        return succeed;
    }
    
    private static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) closeable.close(); 
        }
        catch (IOException e) {
            e.printStackTrace();
        }

    }
}
